﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.SceneManagement;

[Serializable]
public class Instance : ISerializationCallbackReceiver
{
    [CompilerGenerated]
    private static Func<ComponentData, bool> <>f__am$cache8;
    [CompilerGenerated]
    private static Func<ComponentData, string> <>f__am$cache9;
    [CompilerGenerated]
    private static Func<IGrouping<string, ComponentData>, ComponentData> <>f__am$cacheA;
    public ComponentData[] componentDatas;
    public Vector3 eulerAngles;
    public string guid;
    public Vector3 position;
    public string prefabGuid;
    public string prefabName;

    public Instance(string prefabName, Vector3 position)
    {
        this.prefabName = prefabName;
        this.position = position;
    }

    public void DeserializeComponents()
    {
        this.DeserializeComponents(this.componentDatas);
    }

    public void DeserializeComponents(ComponentData[] componentDatas)
    {
        this.DeserializeComponents(componentDatas, this.gameObject);
    }

    public void DeserializeComponents(GameObject target)
    {
        this.DeserializeComponents(this.componentDatas, target);
    }

    public void DeserializeComponents(ComponentData[] componentDatas, GameObject target)
    {
        if (target != null)
        {
            this.componentDatas = componentDatas;
            if (componentDatas != null)
            {
                <DeserializeComponents>c__AnonStorey5C storeyc = new <DeserializeComponents>c__AnonStorey5C();
                IEnumerator<IEditable> enumerator = target.GetComponents(typeof(IEditable)).Cast<IEditable>().GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        storeyc.comp = enumerator.Current;
                        ComponentData data = componentDatas.FirstOrDefault<ComponentData>(new Func<ComponentData, bool>(storeyc.<>m__9D));
                        if ((data != null) && !string.IsNullOrEmpty(data.data))
                        {
                            if (storeyc.comp is ICustomSerialization)
                            {
                                (storeyc.comp as ICustomSerialization).OnDeserialize(data.data);
                            }
                            else
                            {
                                GameJsonUtility.FromJsonOverwrite(data.data, storeyc.comp);
                            }
                        }
                    }
                }
                finally
                {
                    if (enumerator == null)
                    {
                    }
                    enumerator.Dispose();
                }
            }
        }
    }

    public Transform Load(Scene parentScene)
    {
        if (this.transform == null)
        {
            Asset assetByGuid = AssetManager.GetAsset(this.prefabName);
            if (assetByGuid == null)
            {
                assetByGuid = AssetManager.GetAssetByGuid(this.prefabGuid);
            }
            if (assetByGuid == null)
            {
                ErrorMark mark = ErrorMark.Create(string.Format("Could not find prefab '{0}'", this.prefabName), this.position);
                this.transform = mark.transform;
                SceneManager.MoveGameObjectToScene(this.gameObject, parentScene);
                return this.transform;
            }
            this.prefabName = assetByGuid.name;
            if (!string.IsNullOrEmpty(assetByGuid.guid))
            {
                this.prefabGuid = assetByGuid.guid;
            }
            assetByGuid.gameObject.SetActive(false);
            this.transform = UnityEngine.Object.Instantiate<GameObject>(assetByGuid.gameObject).transform;
            assetByGuid.gameObject.SetActive(true);
            this.transform.name = assetByGuid.name;
            SceneManager.MoveGameObjectToScene(this.gameObject, parentScene);
            this.transform.position = this.position;
            this.transform.eulerAngles = this.eulerAngles;
            if (string.IsNullOrEmpty(this.guid))
            {
                this.guid = Guid.NewGuid().ToString();
            }
            this.transform.gameObject.GetOrAddComponent<GameObjectGuid>().value = this.guid;
            NetworkObject component = this.transform.GetComponent<NetworkObject>();
            if (component != null)
            {
                component.NetworklevelInstanceIndex = this.index;
            }
            if (this.transform.GetComponent(typeof(IEditable)) != null)
            {
                this.transform.gameObject.GetOrAddComponent<DestroyEventListener>().onDestroy = new Action(this.OnBeforeSerialize);
            }
            this.DeserializeComponents();
            this.transform.gameObject.SetActive(true);
        }
        return this.transform;
    }

    public void OnAfterDeserialize()
    {
        if ((this.componentDatas != null) && (this.componentDatas.Length == 0))
        {
            this.componentDatas = null;
        }
    }

    public void OnBeforeSerialize()
    {
        this.componentDatas = this.SerializeComponents();
    }

    private ComponentData SeralizeComponent(IEditable target)
    {
        ComponentData data = new ComponentData {
            typeName = target.GetType().Name
        };
        if (target is ICustomSerialization)
        {
            data.data = (target as ICustomSerialization).OnSerialize();
            return data;
        }
        data.data = GameJsonUtility.ToJson(target);
        return data;
    }

    public ComponentData[] SerializeComponents()
    {
        if (this.transform != null)
        {
            if (<>f__am$cache8 == null)
            {
                <>f__am$cache8 = x => !string.IsNullOrEmpty(x.data);
            }
            IEnumerable<ComponentData> first = (from x in this.transform.GetComponents(typeof(IEditable)).Cast<IEditable>() select this.SeralizeComponent(x)).Where<ComponentData>(<>f__am$cache8);
            if ((this.componentDatas != null) && (this.componentDatas.Length > 0))
            {
                if (<>f__am$cache9 == null)
                {
                    <>f__am$cache9 = a => a.typeName;
                }
                if (<>f__am$cacheA == null)
                {
                    <>f__am$cacheA = a => a.First<ComponentData>();
                }
                this.componentDatas = first.Concat<ComponentData>(this.componentDatas).GroupBy<ComponentData, string>(<>f__am$cache9).Select<IGrouping<string, ComponentData>, ComponentData>(<>f__am$cacheA).ToArray<ComponentData>();
            }
            else
            {
                this.componentDatas = first.ToArray<ComponentData>();
            }
            if ((this.componentDatas != null) && (this.componentDatas.Length == 0))
            {
                this.componentDatas = null;
            }
        }
        return this.componentDatas;
    }

    public void SetEulerAngles(Vector3 value)
    {
        this.eulerAngles = value;
        if (this.transform != null)
        {
            this.transform.eulerAngles = value;
        }
    }

    public void SetPosition(Vector3 value)
    {
        this.position = value;
        if (this.transform != null)
        {
            this.transform.position = value;
        }
    }

    public void Unload()
    {
        if (this.transform != null)
        {
            UnityEngine.Object.DestroyImmediate(this.transform.gameObject);
        }
    }

    public GameObject gameObject
    {
        get
        {
            return this.transform.gameObject;
        }
    }

    public int index { get; set; }

    public bool loaded
    {
        get
        {
            return (this.transform != null);
        }
    }

    public Transform transform { get; private set; }

    [CompilerGenerated]
    private sealed class <DeserializeComponents>c__AnonStorey5C
    {
        internal IEditable comp;

        internal bool <>m__9D(Instance.ComponentData x)
        {
            return (x.typeName == this.comp.GetType().Name);
        }
    }

    [Serializable]
    public class ComponentData
    {
        public string data;
        public string typeName;
    }
}

